use std::path::{Path, PathBuf};
use serde::{Deserialize, Serialize};
use thiserror::Error;

#[derive(Debug, Error)]
pub enum FileServiceError {
    #[error("File not found: {0}")]
    FileNotFound(String),
    #[error("Invalid file format: {0}")]
    InvalidFormat(String),
    #[error("File too large: {0}")]
    FileTooLarge(String),
    #[error("IO error: {0}")]
    IoError(String),
    #[error("Permission denied: {0}")]
    PermissionDenied(String),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileInfo {
    pub path: String,
    pub name: String,
    pub extension: String,
    pub size: u64,
    pub created: String,
    pub modified: String,
    pub is_directory: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileFilter {
    pub name: String,
    pub extensions: Vec<String>,
}

pub struct FileService;

impl FileService {
    pub fn new() -> Self {
        Self
    }
    
    pub fn get_video_file_filters() -> Vec<FileFilter> {
        vec![
            FileFilter {
                name: "Video Files".to_string(),
                extensions: vec![
                    "mp4".to_string(),
                    "avi".to_string(),
                    "mov".to_string(),
                    "mkv".to_string(),
                    "wmv".to_string(),
                    "flv".to_string(),
                    "webm".to_string(),
                ],
            },
            FileFilter {
                name: "Audio Files".to_string(),
                extensions: vec![
                    "mp3".to_string(),
                    "wav".to_string(),
                    "aac".to_string(),
                    "flac".to_string(),
                    "ogg".to_string(),
                ],
            },
            FileFilter {
                name: "All Files".to_string(),
                extensions: vec!["*".to_string()],
            },
        ]
    }
    
    pub async fn select_file(
        &self,
        _title: Option<&str>,
        _filters: Option<Vec<FileFilter>>,
        _default_path: Option<&str>,
    ) -> Result<Option<String>, FileServiceError> {
        // 这里使用 Tauri 的对话框 API
        // 在实际实现中，需要调用 Tauri 的对话框插件
        
        // 模拟文件选择对话框
        Ok(None)
    }
    
    pub async fn select_files(
        &self,
        _title: Option<&str>,
        _filters: Option<Vec<FileFilter>>,
        _default_path: Option<&str>,
    ) -> Result<Vec<String>, FileServiceError> {
        // 模拟多文件选择
        Ok(vec![])
    }
    
    pub async fn select_directory(
        &self,
        _title: Option<&str>,
        _default_path: Option<&str>,
    ) -> Result<Option<String>, FileServiceError> {
        // 模拟目录选择
        Ok(None)
    }
    
    pub async fn get_file_info(&self, file_path: &str) -> Result<FileInfo, FileServiceError> {
        let path = Path::new(file_path);
        
        if !path.exists() {
            return Err(FileServiceError::FileNotFound(file_path.to_string()));
        }
        
        let metadata = std::fs::metadata(path)
            .map_err(|e| FileServiceError::IoError(e.to_string()))?;
        
        let name = path.file_name()
            .and_then(|n| n.to_str())
            .unwrap_or("")
            .to_string();
        
        let extension = path.extension()
            .and_then(|e| e.to_str())
            .unwrap_or("")
            .to_string()
            .to_lowercase();
        
        let created = metadata.created()
            .map(|t| format!("{:?}", t))
            .unwrap_or_else(|_| "Unknown".to_string());
        
        let modified = metadata.modified()
            .map(|t| format!("{:?}", t))
            .unwrap_or_else(|_| "Unknown".to_string());
        
        Ok(FileInfo {
            path: file_path.to_string(),
            name,
            extension,
            size: metadata.len(),
            created,
            modified,
            is_directory: metadata.is_dir(),
        })
    }
    
    pub fn validate_video_file(&self, file_path: &str) -> Result<(), FileServiceError> {
        let path = Path::new(file_path);
        
        // 检查文件是否存在
        if !path.exists() {
            return Err(FileServiceError::FileNotFound(file_path.to_string()));
        }
        
        // 检查文件大小 (最大10GB)
        let metadata = std::fs::metadata(path)
            .map_err(|e| FileServiceError::IoError(e.to_string()))?;
        
        if metadata.len() > 10 * 1024 * 1024 * 1024 {
            return Err(FileServiceError::FileTooLarge(
                "File size exceeds 10GB limit".to_string()
            ));
        }
        
        // 检查文件扩展名
        let extension = path.extension()
            .and_then(|e| e.to_str())
            .unwrap_or("")
            .to_lowercase();
        
        let supported_extensions = vec!["mp4", "avi", "mov", "mkv", "wmv", "flv", "webm"];
        
        if !supported_extensions.contains(&extension.as_str()) {
            return Err(FileServiceError::InvalidFormat(format!(
                "Unsupported file format: .{}", extension
            )));
        }
        
        Ok(())
    }
    
    pub async fn create_output_path(
        &self,
        input_path: &str,
        output_format: &str,
        output_dir: Option<&str>,
        suffix: Option<&str>,
    ) -> Result<String, FileServiceError> {
        let input_path = Path::new(input_path);
        
        // 确定输出目录
        let output_dir = match output_dir {
            Some(dir) => PathBuf::from(dir),
            None => input_path.parent()
                .map(|p| p.to_path_buf())
                .unwrap_or_else(|| PathBuf::from(".")),
        };
        
        // 确保输出目录存在
        if !output_dir.exists() {
            std::fs::create_dir_all(&output_dir)
                .map_err(|e| FileServiceError::IoError(e.to_string()))?;
        }
        
        // 获取输入文件名（不含扩展名）
        let stem = input_path.file_stem()
            .and_then(|s| s.to_str())
            .unwrap_or("output");
        
        // 构建输出文件名
        let suffix = suffix.unwrap_or("");
        let output_filename = if suffix.is_empty() {
            format!("{}_converted.{}", stem, output_format)
        } else {
            format!("{}_{}.{}", stem, suffix, output_format)
        };
        
        let output_path = output_dir.join(output_filename);
        
        // 检查输出文件是否已存在，如果存在则添加数字后缀
        let final_path = self.generate_unique_filename(&output_path).await?;
        
        Ok(final_path.to_string_lossy().to_string())
    }
    
    async fn generate_unique_filename(
        &self,
        path: &Path,
    ) -> Result<PathBuf, FileServiceError> {
        if !path.exists() {
            return Ok(path.to_path_buf());
        }
        
        let stem = path.file_stem()
            .and_then(|s| s.to_str())
            .unwrap_or("file");
        
        let extension = path.extension()
            .and_then(|e| e.to_str())
            .unwrap_or("");
        
        let parent = path.parent().unwrap_or(Path::new("."));
        
        for i in 1..100 {
            let new_filename = if extension.is_empty() {
                format!("{} ({})", stem, i)
            } else {
                format!("{} ({}).{}", stem, i, extension)
            };
            
            let new_path = parent.join(new_filename);
            
            if !new_path.exists() {
                return Ok(new_path);
            }
        }
        
        Err(FileServiceError::IoError(
            "Could not generate unique filename".to_string()
        ))
    }
    
    pub async fn list_directory(
        &self,
        dir_path: &str,
        file_types: Option<Vec<&str>>,
    ) -> Result<Vec<FileInfo>, FileServiceError> {
        let path = Path::new(dir_path);
        
        if !path.exists() || !path.is_dir() {
            return Err(FileServiceError::FileNotFound(dir_path.to_string()));
        }
        
        let mut files = Vec::new();
        
        for entry in std::fs::read_dir(path)
            .map_err(|e| FileServiceError::IoError(e.to_string()))? 
        {
            let entry = entry.map_err(|e| FileServiceError::IoError(e.to_string()))?;
            let file_path = entry.path();
            
            if let Ok(file_info) = self.get_file_info(&file_path.to_string_lossy()).await {
                // 过滤文件类型
                if let Some(types) = &file_types {
                    if file_info.is_directory {
                        files.push(file_info);
                    } else if types.contains(&"*") || types.contains(&file_info.extension.as_str()) {
                        files.push(file_info);
                    }
                } else {
                    files.push(file_info);
                }
            }
        }
        
        // 按名称排序
        files.sort_by(|a, b| a.name.cmp(&b.name));
        
        Ok(files)
    }
    
    pub async fn delete_file(&self, file_path: &str) -> Result<(), FileServiceError> {
        std::fs::remove_file(file_path)
            .map_err(|e| FileServiceError::IoError(e.to_string()))
    }
    
    pub async fn file_exists(&self, file_path: &str) -> bool {
        Path::new(file_path).exists()
    }
    
    pub async fn get_file_size(&self, file_path: &str) -> Result<u64, FileServiceError> {
        let metadata = std::fs::metadata(file_path)
            .map_err(|e| FileServiceError::IoError(e.to_string()))?;
        Ok(metadata.len())
    }
}